home *** CD-ROM | disk | FTP | other *** search
/ Windows Undocumented File Formats / Windows Undocumented File Formats.img / CHAP6 / DECOMP.C < prev    next >
C/C++ Source or Header  |  1997-07-15  |  5KB  |  185 lines

  1. /**********************************************************************
  2.  *
  3.  * PROGRAM: DECOMP.C
  4.  *
  5.  * PURPOSE: Decompress a file compressed with Microsoft's COMPRESS.EXE utility.
  6.  * Functionally equivalent to EXPAND.EXE.
  7.  *
  8.  * Copyright 1997, Mike Wallace and Pete Davis
  9.  *
  10.  * Chapter 6, Compression Algorithm and File Formats, from Undocumented Windows
  11.  * File Formats, published by R&D Books, an imprint of Miller Freeman, Inc.
  12.  *
  13.  **********************************************************************/
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include "decomp.h"
  19.  
  20. #define WINSIZE  4096
  21. #define LENGTH(x) ((((x) & 0x0F)) + 3)
  22. #define OFFSET(x1, x2) ((((((x2 & 0xF0) >> 4) * 0x0100) + x1) & 0x0FFF) \
  23.                        + 0x0010)
  24.  
  25. #define FAKE2REAL_POS(x)   ((x) & (WINSIZE - 1))
  26. #define BITSET(byte, bit)  (((byte) & (1<<bit)) > 0)
  27.  
  28. /* This is our Compression Window */
  29. char Window[WINSIZE];
  30.  
  31. /*************************************************
  32.   Decides how many bytes to read, depending on the
  33.   number of bits set in the Bitmap
  34. **************************************************/
  35. int BytesToRead(unsigned char BitMap) {
  36.  
  37.     int TempSum, counter, c;
  38.  
  39.     TempSum = 8;
  40.     for (counter = 0; counter < 8; counter ++) {
  41.         c = BITSET(BitMap, counter);
  42.         TempSum += (1 - BITSET(BitMap, counter));
  43.     }
  44.  
  45.     return TempSum;
  46.  
  47. } /* BytesToRead - end */
  48.  
  49.  
  50. /*************************************************
  51.   Decompresses the data using Microsoft's LZ77
  52. derivative.
  53. **************************************************/ 
  54. void Decompress(FILE *infile, FILE *outfile, long CompSize) {
  55.  
  56.     unsigned char BitMap, byte1, byte2;
  57.     int Length, counter;
  58.     long Offset, CurrPos=0;
  59.  
  60.     for (counter = 0; counter < WINSIZE; counter ++)
  61.         Window[counter] = ' ';
  62.  
  63.     /* Go through until we're done */
  64.     while (CurrPos < CompSize) {
  65.  
  66.         /* Get BitMap and data following it */
  67.         BitMap = fgetc(infile); 
  68.         if (feof(infile)) return;
  69.         (void) BytesToRead(BitMap);
  70.  
  71.         /* Go through and decode data */
  72.         for (counter = 0; counter < 8; counter++) {
  73.  
  74.             /* It's a code, so decode it and copy the data */
  75.             if (!BITSET(BitMap, counter)) {
  76.                 byte1 = fgetc(infile); 
  77.                 if (feof(infile)) return;
  78.                 byte2 = fgetc(infile); 
  79.                 Length = LENGTH(byte2);
  80.                 Offset = OFFSET(byte1, byte2);
  81.  
  82.                 /* Copy data from 'window' */
  83.                 while (Length) {
  84.                     byte1 = Window[FAKE2REAL_POS(Offset)];
  85.                     Window[FAKE2REAL_POS(CurrPos)] = byte1;
  86.                     fputc(byte1, outfile);
  87.                     CurrPos++; 
  88.                     Offset++; 
  89.                     Length--;
  90.                 }
  91.             }/* if */
  92.  
  93.             else {
  94.                 byte1 = fgetc(infile);
  95.                 Window[FAKE2REAL_POS(CurrPos)] = byte1;
  96.                 fputc(byte1, outfile); 
  97.                 CurrPos++;
  98.             }
  99.             if (feof(infile)) return;
  100.  
  101.         } /* for */
  102.  
  103.     } /* while  */
  104.  
  105. } /* Decompress - end */
  106.  
  107.  
  108. /***************************************************
  109.   Read the header at the beginning of the compressed
  110.   file and verity it is a valid input file.
  111. ****************************************************/
  112. void ReadHeader(FILE *infile, FILE *outfile) {
  113.  
  114.     COMPHEADER CompHeader;
  115.     long       CompSize;
  116.  
  117.     fseek(infile, 0, SEEK_END);
  118.     CompSize = ftell(infile);
  119.     fseek(infile, 0, SEEK_SET);
  120.     fread(&CompHeader, sizeof(CompHeader), 1, infile);
  121.     if ((CompHeader.Magic1 != MAGIC1) || (CompHeader.Magic2 != MAGIC2)) {
  122.         printf("Fatal Error:\n");
  123.         printf("  Not a valid Compressed file file!\n");
  124.         return;
  125.     }
  126.  
  127.     printf("Decompressing file from %lu bytes to %lu bytes\n",
  128.           CompSize, CompHeader.DecompSize);
  129.  
  130.     Decompress(infile, outfile, CompHeader.DecompSize);
  131.  
  132.     printf("Done!\n");
  133.  
  134. } /* ReadHeader - end */
  135.  
  136.  
  137. /***************************************************
  138.   Show usage.
  139. ****************************************************/
  140. void Usage( void ) {
  141.  
  142.     printf("Usage:\n");
  143.     printf(" DECOMP file1.ext file2.ext\n\n");
  144.     printf("   file1.ext - Name of compressed file\n");
  145.     printf("   file2.ext - Name of decompressed file\n\n");
  146.  
  147. } /* Usage - end */
  148.  
  149.  
  150. /***************************************************
  151.   Open the file and dump it.
  152. ****************************************************/
  153. int main(int argc, char *argv[]) {
  154.  
  155.     char filename[128];
  156.     FILE *infile, *outfile;
  157.  
  158.     if (argc < 3) {
  159.         Usage();
  160.         return EXIT_FAILURE;
  161.     }
  162.  
  163.     strcpy(filename, argv[1]);
  164.     if ((infile = fopen(filename, "rb")) == NULL) {
  165.         printf("%s does not exist!", filename);
  166.         return EXIT_FAILURE;
  167.     }
  168.  
  169.     strcpy(filename, argv[2]);
  170.     if ((outfile=fopen(filename, "wb")) == NULL) {
  171.         printf("Error opening destination file!");
  172.         return(EXIT_FAILURE);
  173.     }
  174.  
  175.     ReadHeader(infile, outfile);
  176.     fclose(infile);
  177.     fclose(outfile);
  178.  
  179.     return(EXIT_SUCCESS);
  180.  
  181. } /* main - end */
  182.  
  183. /* decomp.c - end */
  184.  
  185.